import { Component, getParentTypeComponent } from "@/stores/edit-pages-store";
import { ComponentConfig } from "@/stores/low-editor-comps-conf";
import { NoticeType } from "antd/es/message/interface";
import { GFS } from "@/hooks/useAssignGlobalProps";
import { axiosInstance } from "@/interfaces";
import { ApiMethod } from "../Setting/selectors/InterfaceConfSelector";
import { EventExtraType } from "./renderProdComponents";
import { cloneDeep } from "lodash-es";

export function handleEvent(
  component: Component,
  componentConfig: Record<string, ComponentConfig>,
  componentRefs: Record<string, any>,
  schema: Component,
  extra?: EventExtraType
) {
  const eventProps: Record<string, any> = {};

  const {id, parentId, name: compName, props: compProps, alias: compAlias} = component
  const curRefComponent = componentRefs.current[id];

  componentConfig[compName].events?.forEach(event => {
    const eventConfig = compProps[event.name];
    if (eventConfig) {
      eventProps[event.name] = async (...args: any[]) => {
        let sendRequestResponse;

        if (Array.isArray(eventConfig.actions)) {
          for (let index = 0; index < eventConfig.actions.length; index++) {
            const action = eventConfig.actions[index];
            if (action.type === "goToLink") {
              const {url, params, blank=true} = action.config;
              const searchObj = getEchoDataObj(params, extra, curRefComponent) || {}
              const searchValue = new URLSearchParams(searchObj).toString()
              const link = url + (searchValue ? `?${searchValue}` : '')
              if(blank){
                window.open(link, '_blank')
              }else{
                window.location.href = link
              }
            } else if (action.type === "showMessage") {
              const mType: NoticeType = action.config.type || "info";
              GFS.message[mType](action.config.text);
            } else if (action.type === "customJS") {
              const func = new Function("context", "args", action.code);
              func(
                {
                  name: compName,
                  props: compProps,
                  showMessage(content: string, mType: NoticeType = "info") {
                    GFS.message.open({
                      content,
                      type: mType,
                    });
                  },
                },
                args
              );
            } else if (action.type === "componentMethod") {
              const refComponent = componentRefs.current[action.config.componentId];
              if (refComponent) {
                refComponent[action.config.method]?.(...args);
              }else{
                throw new Error(`未找到${compAlias}调用的组件`)
              }
            } else if (action.type === "sendRequest") {
              const { api, outputVar, options, ignoreError } = action.config;
              const { url, method, data } = api;

              const apiData = getEchoDataObj(data, extra, curRefComponent)
              // const carryData = ["get", "delete"].includes(method) ? { param: args[0] } : args[0];
              const carryData = apiData ? (["get", "delete"].includes(method) ? { params: apiData } : apiData) : {}
              // console.log("sendRequest🍉", { action, args, extra, data, apiData,carryData,curRefComponent});
              const res = await axiosInstance[method as ApiMethod](url, {...carryData});
              if(res){
                GFS.message.success('请求成功')
                await new Promise(resolve => setTimeout(()=>{
                  return resolve(true)
                }, 600));
              }else{
                await new Promise(reject=>reject(false))
              }
              // sendRequestResponse = res;
            } else if (action.type === "closeDialog"){
              const dialog = getParentTypeComponent(parentId, "Modal", schema)
              if(dialog){
                const component = componentRefs.current[dialog.id]
                component?.close()
              }else{
                throw new Error(`未找到弹窗`)
              }
            }
          }
        }
        // if (sendRequestResponse) {
        //   return Promise.resolve(sendRequestResponse);
        // }
      };
    }
  });
  return eventProps;
}

function getEchoDataObj(data: Record<string, any>, extra: EventExtraType|undefined, curRefComponent: Record<string,any>){
  const {selfDataProperties} = cloneDeep(curRefComponent || {selfDataProperties:{}})
  Object.keys(selfDataProperties).forEach(key=>{
    if(typeof selfDataProperties[key]==='function'){
      selfDataProperties[key] = selfDataProperties[key]()
    }
  })
  
  const {ancestorDataProperties} = extra || {}
  if(!ancestorDataProperties && !curRefComponent)return null
  const propData = {...ancestorDataProperties, ...selfDataProperties}
  const obj: Record<string, any>={}
  Object.keys(data).forEach(key=>{
    let value = data[key]
    const regex = /\$\{([^{}]+)\}/g;
    let matches = [];
    let match;

    while ((match = regex.exec(value)) !== null) {
      matches.push(match);
    }
    matches.forEach(match => {
      const val = getValue(match)
      if(match.input === match[0]){//代表纯粹的变量字符串 eg: '${record.path}'
        value = val
      }else{//代表 变量组成的字符串 eg: '${record.path}abcdef'
        value = typeof val === 'string' ? value.replace(match[0], val) : value.replace(match[0], '${错误的配置}');
      }
    })
    function getValue(match: RegExpExecArray) {
      const propertyArr = match[1].split('.');
      let result: any
      propertyArr.some((key,kIndex)=>{
        const obj = kIndex === 0 ? propData : result
        if(obj[key]){
          result = obj[key]
          return false
        }else{
          result = undefined
          return true
        }
      })
      return result
    }
    obj[key] = value
  })
  return obj
}